"""
Alpha Manager 
Entidades de la base de datos
"""

import transaction
import cryptacular.bcrypt
from pyramid.security import Allow
from pyramid.security import Everyone
from pyramid.security import Authenticated
from sqlalchemy.orm import relationship
from sqlalchemy import Table
from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import relation
from sqlalchemy.orm import backref
from sqlalchemy.types import DateTime
from sqlalchemy.orm import column_property
from sqlalchemy.orm import synonym
from sqlalchemy.orm import joinedload
from sqlalchemy.types import Integer
from sqlalchemy.types import Unicode
from sqlalchemy.types import Boolean
from sqlalchemy.types import LargeBinary
from sqlalchemy.types import UnicodeText
from sqlalchemy.sql import func
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
from zope.sqlalchemy import ZopeTransactionExtension
from datetime import datetime  
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
from alpha.modelos import Base


crypt = cryptacular.bcrypt.BCRYPTPasswordManager()

def hash_password(password):
    return unicode(crypt.encode(password))


"""
Tablas de la base de datos
"""

"""
Tablas de asociacion 
"""
class AssociationRol(Base):
	__tablename__ = 'associationRol'
	left_id = Column(Integer, ForeignKey('usuario.id_usuario'), primary_key=True)
	right_id = Column(Integer, ForeignKey('rol.id_rol'), primary_key=True)
	extra_data = Column(Unicode(50))
	rol = relationship("Rol", backref="usuario_assocs")

class Association(Base):
	__tablename__ = 'association'
	left_id = Column(Integer, ForeignKey('proyecto.id'), primary_key=True)
	right_id = Column(Integer, ForeignKey('tipoItem.id'), primary_key=True)
	extra_data = Column(Unicode(50))
	tipoItem = relationship("TipoItem", backref="proyecto_assocs")



"""
Tabla Usuario: almacena los datos referentes a los usuario
"""
class Usuario(Base):
	
    __tablename__ = 'usuario'	
    id_usuario = Column(Integer, primary_key=True)
    nombreUsuario = Column(Unicode(20), unique=True)
    _password = Column('password', Unicode(60))
    nombre = Column(Unicode(50))
    apellido = Column(Unicode(50))
    telefono = Column(Integer)
    nroDocumento = Column(Integer)
    fechaCreacion = Column(DateTime, default=datetime.now)
    mail = Column(Unicode(50))
    
    asociacion = relationship("AssociationRol", backref="usuario")


    def __init__(self, nombreUsuario, password, nombre, apellido, telefono, nroDocumento, mail):
        self.nombreUsuario = nombreUsuario
        self.password = password
        self.nombre = nombre
        self.apellido= apellido
        self.telefono= telefono
        self.nroDocumento= nroDocumento
        self.mail = mail
        
    def _get_password(self):
        return self._password

    def _set_password(self, password):
        self._password = hash_password(password)
		
    password = property(_get_password, _set_password)
    password = synonym('_password', descriptor=password)
 
    @classmethod
    def get_by_username(cls, nombreUsuario):
        return DBSession.query(cls).filter(cls.nombreUsuario == nombreUsuario).first()

    @classmethod
    def check_password(cls, nombreUsuario, password):
        usuario = cls.get_by_username(nombreUsuario)
        if not usuario:
            return False
        return crypt.check(usuario.password, password)

	def getNombre(self):
		return self.nombre
	
	def getApellido(self):
		return self.apellido
	
	def getTelefono(self):
		return self.telefono
	
	def getNroDocumento(self):
		return self.nroDocumento
	
	def getMail(self):
		return self.mail
	
	def setNombre(self, nombre):
		self.nombre= nombre
	
	def setApellido(self, apellido):
		self.apellido= apellido
	
	def setTelefono(self, telefono):
		self.telefono= telefono
	
	def setNroDocumento(self, nroDocumento):
		self.nroDocumento= nroDocumento
	
	def setMail(self, mail):
		self.mail= mail
        


"""
Tabla Rol
"""
class Rol(Base):

	__tablename__ = 'rol'
	id_rol = Column(Integer, autoincrement=True, primary_key=True)
	nombreRol = Column(Unicode(70), unique=True)
	descripcion = Column(Unicode(100))
	fechaCreacion = Column(DateTime, default=datetime.now)

	def __init__(self, nombreRol,descripcion):
		self.nombreRol = nombreRol
		self.descripcion = descripcion    

	def getNombre(self):
		return self.nombreRol
	
	def getDescripcion(self):
		return self.descripcion
	
	def getFecha(self):
		return self.fechaCreacion
	
	def setDescripcion(self, descripcion):
		self.descripcion= descripcion
    

class Proyecto(Base):
	__tablename__ = 'proyecto'
	id = Column(Integer, primary_key=True)
	nombre= Column(Unicode(50), unique=True)
	descripcion= Column(Unicode(300))
	fechaCreacion = Column(DateTime, default=datetime.now)
	complejidad= Column(Integer)
	estado= Column(Unicode(20))
	nroFases= Column(Integer)
	fase = relationship("Fase", backref="proyecto")
	asociacion = relationship("Association", backref="proyecto")


	def __init__(self, nombre, descripcion, nroFases):
		self.nombre= nombre
		self.descripcion= descripcion
		self.complejidad= 0
		self.estado= 'No iniciado'
		self.nroFases= nroFases

	def getNombre(self):
		return self.nombre

	def getDescripcion(self):
		return self.descripcion

	def getFecha(self):
		return self.fechaCreacion

	def getComplejidad(self):
		return self.complejidad

	def getEstado(self):
		return self.estado

	def getNroFases(self):
		return self.nroFases

	def getFases(self):
		return self.fase

	def setEstado(self, nuevoEstado):
		self.estado= nuevoEstado

	def setDescripcion(self, descripcion):
		self.descripcion= descripcion


class Fase(Base):
	__tablename__ = 'fase'
	id = Column(Integer, primary_key=True)
	posicionFase= Column(Integer)
	nombre= Column(Unicode(50), unique=True)
	descripcion= Column(Unicode(300))
	nroItems = Column(Integer)
	nroLB = Column(Integer)
	estado = Column(Unicode(20))
	proyecto_id = Column(Integer, ForeignKey('proyecto.id'))

	def __init__(self, nombre, nroItems, posicionFase,descripcion,nroLB,estado):
		self.nombre= nombre
		self.nroItems= nroItems
		self.posicionFase = posicionFase
		self.descripcion = descripcion
		self.nroLB = nroLB
		self.estado = estado

	def getNombre(self):
		return self.nombre

	def getDescripcion(self):
		return self.descripcion

	def getPosicionFase(self):
		return self.posicionFase

	def getNroItems(self):
		return self.nroItems

	def getEstado(self):
		return self.estado

	def getNroLB(self):
		return self.nroLB

	def setEstado(self, nuevoEstado):
		self.estado= nuevoEstado

	def setDescripcion(self, descripcion):
		self.descripcion= descripcion
		
	def setNroItems(self, cantidad):
		self.nroItems= cantidad
	
	def setNroLB(self, cantidad):
		self.nroLB= cantidad
class TipoItem(Base):
	__tablename__ = 'tipoItem'
	id = Column(Integer, primary_key=True)
	nombre= Column(Unicode(50))
	descripcion= Column(Unicode(50))

	def __init__(self, nombre):
		self.nombre= nombre

	def getNombre(self):
		return self.nombre

	def getDescripcion(self):
		return self.descripcion

	def setDescripcion(self, descripcion):
		self.descripcion= descripcion



"""
Clase RootFactory para los permisos
"""

class RootFactory(object):
    __acl__ = [ (Allow, Everyone, 'view'),
                (Allow, Authenticated, 'edit') ]


    def __init__(self, request):
        pass
